#ifndef __LOGO_LIB_H__
#define __LOGO_LIB_H__

#include <stdio.h>
#include "iexec.h"


/* 
 * These messages are sent by UI.
 *  GO, STEP_OVER, STEP_INTO, STEP_OUT has no parameters.
 *  STEP_TO's wParam is the "TO" lineno.
 * 
 * The interpretor send MSG_DEBUG_ACK to UI with wParam set as current lineno,
 *  when it finishes the debug command.
 */

#define MSG_DEBUG_GO                     (WM_USER + 100)
#define MSG_DEBUG_FIRST                  MSG_DEBUG_GO
#define MSG_DEBUG_STEP_OVER              (WM_USER + 101)
#define MSG_DEBUG_STEP_INTO              (WM_USER + 102)
#define MSG_DEBUG_STEP_OUT               (WM_USER + 103)
#define MSG_DEBUG_STEP_TO                (WM_USER + 104)
#define MSG_DEBUG_STOP                   (WM_USER + 105)
#define MSG_DEBUG_START                  (WM_USER + 106)
#define MSG_DEBUG_LAST                   MSG_DEBUG_START


typedef struct tag_list_node_t {
   struct tag_list_node_t* next;
   char* id_str;
} list_node_t;

typedef enum { NoneVal = 0, NumericVal, StringVal} value_type_t;

class value_t
{
public:
   value_type_t      type;
   union {
      double val;
      char* str;
   };

public:
   value_t ();
   virtual ~value_t ();
   void copy_value (value_t* src);
   void copy_string(const char* str);
};

#ifdef __cplusplus
extern "C" 
{
#endif /* __cplusplus */

typedef void* node_handle_t;
typedef void* exe_handle_t;

void start_scanning (FILE* file);
node_handle_t parse ();
void print_parse_tree (node_handle_t root);

exe_handle_t create_exe_handle();
void clear_for_rerun(exe_handle_t h);
void delete_exe_handle(exe_handle_t h);

void interpret (exe_handle_t hexe, node_handle_t t);
void user_abort(exe_handle_t hexe, bool abort);
bool get_debug_mode(exe_handle_t hexe);
void set_debug_mode(exe_handle_t hexe, bool debug);
/* returns non-zero on error */
int check_syntax_error();
void set_exec_obj (exe_handle_t hexe, i_exec_t* exec);
void save_thread_id(exe_handle_t hexe);

void debug_step_over(exe_handle_t hexe);
void debug_step_into(exe_handle_t hexe);
void debug_step_out(exe_handle_t hexe);
void debug_step_to(exe_handle_t hexe, unsigned int lineno);
void debug_start(exe_handle_t hexe);
void debug_go(exe_handle_t hexe);
void debug_stop(exe_handle_t hexe);
void debug_toggle_breakpoint(exe_handle_t hexe, unsigned int lineno);
void debug_free_breakpointlist(exe_handle_t hexe);
/* When text edit adds a new line or removes a new line,
 * current breakpoints need to be adjusted.
 * if insert is true, then it means a new line is added at lineno.
 * if insert is false, then it means a line at lineno is removed. 
 */
void debug_adjust_breakpoints(exe_handle_t hexe, bool insert, unsigned int lineno);
bool debug_find_breakpoint (exe_handle_t hexe, unsigned int lineno);

/* Call debug_get_call_stack to get stack information:
 *  nIdx is the stack pointer, -1 is the stack top, nIdx is updated by this function, 
 *   moved to the next in the stack.
 *  To get all the items in stack, call this routine, until the function returns -1.
 *  In buf, the routine name is copied.
 *  Line nunber is stored in *lineno.
 *
 * It returns 0 on success, -1 of error. 
 */
int debug_get_call_stack(exe_handle_t hexe, int* nIdx, char* buf, int buflen, int* lineno);

typedef void* var_handle_t;

var_handle_t debug_get_first_variable(exe_handle_t hexe, int nStackIdx, const char** name, value_t** val);
var_handle_t debug_get_next_variable(var_handle_t hvar, const char** name, value_t** val);
var_handle_t debug_find_varriable_by_string (exe_handle_t hexe, int nStackIdx, const char* name);
int debug_change_variable_numeric_value(var_handle_t hvar, double v);
int debug_change_variable_string_value(var_handle_t hvar, const char* s);

int debug_get_routine_lineno_range(exe_handle_t hexe, int nStackIdx, int* start, int* end);

#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __LOGO_LIB_H__ */
